package pers.burgess.fsm.client.core;

import java.net.Socket;
import java.net.SocketException;
import com.sun.istack.internal.NotNull;
import pers.burgess.fsm.model.Message;
import java.io.*;
import java.net.Socket;

public class Client {
	
    private Socket client = null;
    private ClientStatus clientStatus = ClientStatus.READY;
    private ClientStatusChangedListener clientListener = null;
    private ObjectOutputStream objectOutputStream = null;
    private ObjectInputStream objectInputStream = null;

    public Client () {
        if (this.clientListener != null)
            this.clientListener.onChanged(ClientStatus.READY);
    }

    public void connect (@NotNull String serverAddress, @NotNull int port) {
        if (this.clientListener != null) {
            this.clientListener.onChanged(ClientStatus.DO_CONNECT);
        }
        this.clientStatus = ClientStatus.DO_CONNECT;
        try {
            this.client = new Socket(serverAddress, port);
            this.objectOutputStream = new ObjectOutputStream(this.client.getOutputStream());
            this.objectInputStream = new ObjectInputStream(this.client.getInputStream());
        	if (this.clientListener != null) {
                this.clientListener.onChanged(ClientStatus.CONNECTING);
        	}
            this.clientStatus = ClientStatus.CONNECTING;
        } catch (Exception e) {
        	
        	if (this.clientListener != null) {
                this.clientListener.onChanged(ClientStatus.CONNECT_FAILED);
        	}
            this.clientStatus = ClientStatus.CONNECT_FAILED;
            
            if (this.clientListener != null) {
                this.clientListener.onChanged(ClientStatus.READY);
        	}
            this.clientStatus = ClientStatus.READY;
        }
    }

    public Message requestServer (Message message, boolean haveResponse) throws IOException, ClassNotFoundException {
        if (this.objectOutputStream != null) {
            this.objectOutputStream.writeObject(message);
            this.objectOutputStream.flush();
        }
        if (this.objectInputStream != null && haveResponse) {
            return (Message)this.objectInputStream.readObject();
        }
        return null;
    }
    
    public Message readMessage () throws IOException, ClassNotFoundException {
    	 if (this.objectInputStream != null) {
             return (Message)this.objectInputStream.readObject();
         }
         return null;
    }

    private void destroy () throws IOException {
        if (this.client != null)
            this.client.close();
        if (this.objectInputStream != null)
            this.objectInputStream.close();
        if (this.objectOutputStream != null)
            this.objectOutputStream.close();
    }

    public void disconnect () {
        try {
            destroy();
            if (this.clientListener != null) {
                this.clientListener.onChanged(ClientStatus.DISCONNECT);
            }
            this.clientStatus = ClientStatus.DISCONNECT;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (this.clientListener != null) {
                this.clientListener.onChanged(ClientStatus.READY);
            }
            this.clientStatus = ClientStatus.READY;
        }
    }

    public void setClientListener(ClientStatusChangedListener clientListener) {
        this.clientListener = clientListener;
    }

    public ClientStatusChangedListener getClientListener() {
        return clientListener;
    }

	public ClientStatus getClientStatus() {
		return clientStatus;
	}

	public void setClientStatus(ClientStatus clientStatus) {
		this.clientStatus = clientStatus;
	}
    
    
}
